﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ufida.u9.ait.openapi.utils;
using UFIDA.U9.Base;
using UFIDA.U9.Base.Currency;
using UFIDA.U9.Base.UOM;
using UFIDA.U9.CBO.FI.Tax;
using UFIDA.U9.CBO.HR.Department;
using UFIDA.U9.CBO.HR.Operator;
using UFIDA.U9.CBO.SCM.AccrueBy;
using UFIDA.U9.CBO.SCM.Customer;
using UFIDA.U9.CBO.SCM.Enums;
using UFIDA.U9.CBO.SCM.Item;
using UFIDA.U9.CBO.SCM.ProjectTask;
using UFIDA.U9.CBO.SCM.TIBy;
using UFIDA.U9.CBO.SCM.Warehouse;
using UFIDA.U9.SM.Ship;
using UFIDA.U9.SM.Ship.Proxy;
using UFIDA.U9.SM.ShipPlan;
using UFIDA.U9.SM.SO;
using UFSoft.UBF.Business;

namespace ufida.u9.ait.openapi
{
    internal class ShipBase
    {
        public static void DeleteDoc(List<ShipAITDTOData> data)
        {
            try
            {
                using (ISession session = Session.Open())
                {
                    foreach (var dto in data)
                    {
                        Ship doc = Ship.Finder.Find($"DocNo='{dto.DocNo}'");
                        if (doc != null)
                            doc.Remove();
                    }

                    session.Commit();
                }
            }
            catch (Exception ex)
            {
                LogUtils.Log("AIT删除失败\r\n" + ex.Message);
            }
        }

        public static Ship SubmitDoc(Ship doc)
        {
            doc = doc.Key.GetEntity();
            if (doc.Status != ShipStateEnum.Creates)
                throw new Exception($"单号[{doc.DocNo}]状态不为开立!");

            ShipmentSubmitProxy bp = new ShipmentSubmitProxy();
            bp.SysVersion = doc.SysVersion;
            bp.ShipmentKey = doc.ID;
            UFIDA.U9.SM.Common.ErrorMessageDTOData errorMessageDTO = bp.Do();
            if (errorMessageDTO != null && !string.IsNullOrEmpty(errorMessageDTO.ErrorMessage))
            {
                throw new Exception(errorMessageDTO.ErrorMessage);
            }

            return doc;
        }
        public static Ship ApproveDoc(Ship doc)
        {
            U9Utils.ClearCache();

            doc = doc.Key.GetEntity();
            if (doc.Status == ShipStateEnum.Creates)
            {
                SubmitDoc(doc);
            }

            doc = doc.Key.GetEntity();
            if (doc.Status != ShipStateEnum.Approving)
                throw new Exception($"单号[{doc.DocNo}]状态不为审核中!");

            ShipmentApproveProxy bp = new ShipmentApproveProxy();
            bp.SysVersion = doc.SysVersion;
            bp.IsUnApprove = false;
            bp.ShipmentKey = doc.ID;
            UFIDA.U9.SM.Common.ErrorMessageDTOData errorMessageDTO = bp.Do();
            if (errorMessageDTO != null && !string.IsNullOrEmpty(errorMessageDTO.ErrorMessage))
            {
                throw new Exception(errorMessageDTO.ErrorMessage);
            }

            return doc;
        }

        public static Ship UnApproveDoc(Ship doc)
        {
            doc = doc.Key.GetEntity();
            if (doc.Status != ShipStateEnum.Approving)
                throw new Exception($"单号[{doc.DocNo}]状态不为审核中!");

            ShipmentApproveProxy bp = new ShipmentApproveProxy();
            bp.SysVersion = doc.SysVersion;
            bp.IsUnApprove = true;
            bp.ShipmentKey = doc.ID;
            UFIDA.U9.SM.Common.ErrorMessageDTOData errorMessageDTO = bp.Do();
            if (errorMessageDTO != null && !string.IsNullOrEmpty(errorMessageDTO.ErrorMessage))
            {
                throw new Exception(errorMessageDTO.ErrorMessage);
            }

            return doc;
        }

        public static Ship CreateDoc(ShipAITDTOData dto)
        {
            Ship doc = null;
            using (ISession session = Session.Open())
            {
                doc = Ship.Create();
                CreateHead(doc, dto);
                CreateLines(doc, dto);

                session.Commit();
            }

            return doc;
        }

        private static void CreateLines(Ship doc, ShipAITDTOData dto)
        {
            foreach (var linedto in dto.ShipLines)
            {
                ShipLine line = ShipLine.Create(doc);

                LineDefault(line, linedto);
                //来源单据
                if (linedto.SrcDocInfo != null && linedto.SrcDocInfo.SrcDocType > 0)
                {
                    //有来源信息且非手工
                    if (linedto.SrcDocInfo.SrcDocType == 1)
                    {
                        //来源SO
                        //SO  销售订单    1   
                        FromSOLine(line, linedto);
                    }
                    else if (linedto.SrcDocInfo.SrcDocType == 2)
                    {
                        //来源 出货计划
                        FromShipPlan(line, linedto);
                    }
                    else
                    {
                        throw new Exception($"SrcDocType:[{linedto.SrcDocInfo.SrcDocType}暂不支持]");
                    }
                }
                LineQty(line, linedto);
                LineMny(line, linedto);
                //税子行
                LineTax(line);
            }
        }

        private static void FromShipPlan(ShipLine line, ShipLineAITDTOData linedto)
        {
            Ship doc = line.Ship;

            String path = $"ShipPlan.DocNo='{linedto.SrcDocInfo.DocNo}' and DocLineNo={linedto.SrcDocInfo.DocLineNo}";
            ShipPlanLine planline= ShipPlanLine.Finder.Find(path);
            if (planline == null) throw new Exception($"查询出货计划行失败,path:[{path}]");
            ShipPlan plan=planline.ShipPlan;

            if (linedto.ItemInfo.ItemCode != planline.ItemInfo.ItemCode)
                throw new Exception($"来源单据物料[{planline.ItemInfo.ItemCode}]与传入物料[{linedto.ItemInfo.ItemCode}]不同");

            //来源单据 赋值
            if(planline.Project != null)
            {
                line.Project = planline.Project;//项目
            }
            line.SrcSysVersion = planline.SysVersion;
            line.SrcDocVer = plan.Version;
            line.SrcDocType = ShipSrcDocTypeEnum.GetFromValue(2);//来源单据类型=出货计划
            line.SrcDocTransType = plan.DocType.ID;
            line.SrcDocOwnedOrg = doc.Org;
            line.SrcDocNo = plan.DocNo;
            line.SrcDocKey = plan.ID;
            line.SrcDocDate = plan.BusinessDate;
            line.SrcDocLineNo = planline.DocLineNo;
            line.SrcDocLineKey = planline.ID;
            line.SrcDocPriceTC = planline.PriceTC;

            line.ShipPlanOrg = plan.Org;
            line.ShipPlanID = plan.ID;
            line.ShipPlanLineID = planline.ID;
            line.ShipPlanDocNo = plan.DocNo;

            //来源SO 赋值
            SOShipline shipline = SOShipline.Finder.FindByID(planline.SrcDocSubLine);
            if (shipline != null)
            {
                SOLine soline = shipline.SOLine;
                SO so = soline.SO;
                line.SOVer = so.Version;
                line.SOTDocType = so.DocType.ID;
                line.SOSysVersion = so.SysVersion;
                line.SOSubLineNo = shipline.DocSubLineNo;
                line.SOSubLineKey = shipline.ID;
                line.SOOwnedOrg = doc.Org;
                line.SONo = so.DocNo;
                line.SOLineNo = soline.DocLineNo;
                line.SOLineKey = soline.ID;
                line.SOKey = so.ID;
                line.SODate = so.BusinessDate;
            }

            //其它
            doc.SrcDocType = ShipSrcDocTypeEnum.GetFromValue(2);//来源单据类型=出货计划
            doc.PreRecObject = UFIDA.U9.CBO.SCM.PreRecPolicy.PreRecObjectEnum.GetFromValue(2);//预收环节=订单
            doc.IsNoSOShipment = false;
            doc.ShipmentRule = doc.OrderBy.Customer.ShippmentRule;//出货原则
            line.ShipmentRule = doc.ShipmentRule;
            line.PriceSource = PriceSourceEnum.GetFromValue(3);//价格来源=来源单据
            line.PreRecObject = doc.PreRecObject;
        }

        private static void LineTax(ShipLine line)
        {
            ShipTax tax = ShipTax.Create(line);
            tax.TaxRate = line.TaxRate;
            tax.TaxAmountTC = line.TotalTaxTC;
            tax.TaxAmountFC = line.TotalTax;
            tax.TaxAmount = line.TotalTax;
            tax.Tax = line.TaxSchedule.TaxScheduleTaxs[0].Tax;
            tax.Org = line.Org;
            tax.AC = line.AC;
        }

        private static void LineTaxSchedule(ShipLine line, ShipLineAITDTOData linedto)
        {
            Ship doc = line.Ship;
            ItemMaster item = line.ItemInfo.ItemID;

            //税组合 单体
            if (line.TaxSchedule == null)
            {
                if (linedto.TaxSchedule != null)
                {
                    //优先传入
                    line.TaxSchedule = EntityUtils.GetEntityByCode<TaxSchedule>(linedto.TaxSchedule.Code);
                }
                else if (doc.TaxSchedule != null)
                {
                    //其次单头
                    line.TaxSchedule = doc.TaxSchedule;
                }
                else if (item.SaleInfo.SaleTaxSchedule != null)
                {
                    //其次料品
                    line.TaxSchedule = item.SaleInfo.SaleTaxSchedule;
                }
                if (line.TaxSchedule == null) throw new Exception("TaxSchedule为空");
            }
            line.TaxRate = line.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate;//税率
        }

        private static void LineMny(ShipLine line, ShipLineAITDTOData linedto)
        {
            Ship doc = line.Ship;
            if(linedto.SrcDocInfo != null)
            {
                if (linedto.SrcDocInfo.SrcDocType == 1)
                {
                    //来源 销售订单
                    SOShipline shipline = SOShipline.Finder.FindByID(line.SrcDocSubLineKey);
                    if (shipline == null) throw new Exception("查找销售订单计划行失败!");
                    SOLine soline = shipline.SOLine;
                    SO so = soline.SO;

                    doc.TC = so.TC;
                    doc.AC = so.AC;
                    doc.FC = so.FC;
                    line.TCToACExRate = so.TCToACExchRate;
                    line.TaxSchedule = soline.TaxSchedule;//税组合
                    line.TaxRate = line.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate;//税率
                                                                                   //单价金额
                    line.OrderPriceTC = soline.OrderPriceTC;//定价(原币)
                    line.OrderPrice = soline.OrderPriceTC * line.TCToACExRate;//定价(核币)
                    line.TotalMoneyTC = line.QtyPriceAmount * line.OrderPriceTC;//价税合计(原币)
                    line.TotalMoneyTC = U9Utils.GetRoundMoney(doc.TC, line.TotalMoneyTC);
                    line.TotalMoney = line.TotalMoneyTC * line.TCToACExRate;//核币
                    line.TotalMoneyFC = line.TotalMoney;//本币

                }else if(linedto.SrcDocInfo.SrcDocType == 2)
                {
                    //来源 出货计划
                    ShipPlanLine planline = ShipPlanLine.Finder.FindByID(line.SrcDocLineKey);
                    if (planline == null) throw new Exception("查找出货计划行失败!");
                    ShipPlan plan = planline.ShipPlan;

                    SOShipline shipline = SOShipline.Finder.FindByID(planline.SrcDocSubLine);
                    if (shipline == null) throw new Exception("查询订单计划行失败!");
                    SOLine soline = shipline.SOLine;
                    SO so = soline.SO;

                    doc.TC = plan.TC;
                    doc.AC = plan.AC;
                    doc.FC = plan.AC;
                    line.TCToACExRate = planline.TCToACRate;
                    line.TaxSchedule = soline.TaxSchedule;//税组合
                    line.TaxRate = line.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate;//税率
                    //单价金额                                                               
                    line.OrderPriceTC = planline.PriceTC;//定价(原币)
                    line.OrderPrice = planline.PriceTC * line.TCToACExRate;//定价(核币)
                    line.TotalMoneyTC = line.QtyPriceAmount * line.OrderPriceTC;//价税合计(原币)
                    line.TotalMoneyTC = U9Utils.GetRoundMoney(doc.TC, line.TotalMoneyTC);
                    line.TotalMoney = line.TotalMoneyTC * line.TCToACExRate;//核币
                    line.TotalMoneyFC = line.TotalMoney;//本币
                }
            }
            else
            {
                //单价/金额
                LineTaxSchedule(line, linedto);
                line.OrderPriceTC = linedto.OrderPrice;//定价
                line.OrderPrice = linedto.OrderPrice;//定价(核币)
                line.TotalMoneyTC = linedto.TotalMoney;//金额(原币)
                line.TotalMoney = linedto.TotalMoney;//核币
                line.TotalMoneyFC = linedto.TotalMoney;//本币
            }
            line.SystemPriceTC = line.OrderPriceTC;
            line.SystemPrice = line.OrderPrice;
            line.FinallyPriceTC = line.OrderPriceTC;
            line.FinallyPrice = line.OrderPrice;
            line.SignInTotalMoneyFC = line.TotalMoneyFC;
            //未税金额
            line.TotalNetMoneyTC = line.TotalMoneyTC / (1 + line.TaxRate);//原币
            line.TotalNetMoneyTC = U9Utils.GetRoundMoney(doc.TC, line.TotalNetMoneyTC);
            line.TotalNetMoney = line.TotalMoney / (1 + line.TaxRate);//核币
            line.TotalNetMoney = U9Utils.GetRoundMoney(doc.TC, line.TotalNetMoney);
            line.TotalNetMoneyFC = line.TotalNetMoney;//本币
            
            line.FutureCostTC = line.TotalNetMoneyTC;
            line.FutureCostAC = line.TotalNetMoney;
            line.FutureCostFC = line.TotalNetMoneyFC;

            line.SignInTotalMoneyNoTaxFC = line.TotalNetMoneyFC;
            //税额
            line.TotalTaxTC = line.TotalMoneyTC - line.TotalNetMoneyTC;//原币
            line.TotalTax = line.TotalMoney - line.TotalNetMoney;//核币
            line.TotalTaxFC = line.TotalMoneyFC - line.TotalNetMoneyFC;//本币
            line.SignInTotalTaxFC = line.TotalTaxFC;
        }

        private static void LineQty(ShipLine line, ShipLineAITDTOData linedto)
        {
            Ship doc = line.Ship;
            ItemMaster item = line.ItemInfo.ItemID;
            //计量单位
            line.WeightUom = item.WeightUom;//重量单位
            line.VolumeUom = item.BulkUom;//体积单位
            line.TradeUom = item.SalesUOM;//销售单位
            line.TradeBaseUom = item.SalesUOM.BaseUOM;
            line.PriceUom = item.PriceUOM;//计价单位
            line.PriceBaseUom = item.PriceUOM.BaseUOM;
            line.InvMainUOM = item.InventoryUOM;//库存单位
            line.InvUom = item.InventorySecondUOM;
            line.InvBaseUom = item.InventorySecondUOM.BaseUOM;
            line.CostUom = item.CostUOM;//成本单位
            line.CostBaseUom = item.CostUOM.BaseUOM;
            if (linedto.SrcDocInfo != null)
            {
                //存在来源单据
                if (linedto.SrcDocInfo.SrcDocType == 1)
                {
                    //来源 销售订单
                    SOShipline shipline = SOShipline.Finder.FindByID(line.SrcDocSubLineKey);
                    if (shipline == null) throw new Exception("查找销售订单计划行失败!");
                    SOLine soline = shipline.SOLine;

                    line.TradeUom = shipline.TU;//销售单位
                    line.TradeBaseUom = shipline.TBU;
                    line.PriceUom = shipline.PU;//计价单位
                    line.PriceBaseUom = shipline.PBU;
                }
                else if (linedto.SrcDocInfo.SrcDocType == 2)
                {
                    //来源 出货计划
                    ShipPlanLine planline = ShipPlanLine.Finder.FindByID(line.SrcDocLineKey);
                    if (planline == null) throw new Exception("查找出货计划行失败!");
                    ShipPlan plan = planline.ShipPlan;

                    line.TradeUom = planline.TradeUom;//销售单位
                    line.TradeBaseUom = planline.TradeBaseUom;
                    line.PriceUom = planline.PriceUom;//计价单位
                    line.PriceBaseUom = planline.PriceBaseUom;
                }
            }
            
            //如果DTO传入,则直接覆盖
            if (linedto.TradeUom != null)
            {
                //销售单位
                UOM uom = EntityUtils.GetEntityByCode<UOM>(linedto.TradeUom.Code);
                line.TradeUom = uom;
                line.TradeBaseUom = uom.BaseUOM;
            }
            if (linedto.PriceUom != null)
            {
                //计价单位
                UOM uom = EntityUtils.GetEntityByCode<UOM>(linedto.PriceUom.Code);
                line.PriceUom = uom;
                line.PriceBaseUom = uom.BaseUOM;
            }
            if (linedto.InvUom != null)
            {
                //库存单位
                UOM uom = EntityUtils.GetEntityByCode<UOM>(linedto.InvUom.Code);
                line.InvUom = uom;
                line.InvMainUOM = uom;
                line.InvBaseUom = uom.BaseUOM;
            }
            if (linedto.CostUom != null)
            {
                //成本单位
                UOM uom = EntityUtils.GetEntityByCode<UOM>(linedto.CostUom.Code);
                line.CostUom = uom;
                line.CostBaseUom = uom.BaseUOM;
            }

            //数量
            if (linedto.ShipQtyTUAmount == 0) throw new Exception("ShipQtyTUAmount必填");
            line.ShipQtyTUAmount = linedto.ShipQtyTUAmount;//本次出货数量1
            if (linedto.QtyPriceAmount != 0)
            {
                line.QtyPriceAmount = linedto.QtyPriceAmount;//计价数量
            }
            else
            {
                line.QtyPriceAmount = linedto.ShipQtyTUAmount;
            }
            if (linedto.ShipQtyInvAmount != 0)
            {
                line.ShipQtyInvAmount = linedto.ShipQtyInvAmount;//出货数量(库存单位)
            }
            else
            {
                line.ShipQtyInvAmount = line.ShipQtyTUAmount;
            }
            if (linedto.ShipQtyCostAmount != 0)
            {
                line.ShipQtyCostAmount = linedto.ShipQtyCostAmount;//成本数量
            }
            else
            {
                line.ShipQtyCostAmount = line.QtyPriceAmount;
            }
            line.SaleCostAmount = line.ShipQtyCostAmount;//实际成本量

            //转化率 5位小数
            line.TUPUConvRatio = Math.Round(line.QtyPriceAmount / line.ShipQtyTUAmount, 5);//销售-计价
            line.SignInTUPUConvRatio = line.TUPUConvRatio;//签收销售-计价
            line.TUInvConvRatio = Math.Round(line.ShipQtyInvAmount / line.ShipQtyTUAmount, 5);//销售-库存
            line.TUCUConvRatio = Math.Round(line.ShipQtyCostAmount / line.ShipQtyInvAmount, 5);//库存-成本

            //库位处理
            LineLocation(line, linedto);
        }
        /// <summary>
        /// 库位处理
        /// </summary>
        /// <param name="line"></param>
        /// <param name="linedto"></param>
        private static void LineLocation(ShipLine line, ShipLineAITDTOData linedto)
        {
            if (!string.IsNullOrEmpty(linedto.Location?.Code))
            {
                //库位编码非空
                ShipLineLocation loc= ShipLineLocation.Create(line);
                loc.Org = line.Org;
                loc.LotInvalidationDate = line.LotInvalidationDate;
                loc.Lot = line.LotInfo;
                loc.LocationQtyTUAmount = line.ShipQtyTUAmount;
                loc.LocationQtyTBUAmount = line.ShipQtyTBUAmount;
                loc.LocationQtyInvAmount = line.ShipQtyInvAmount;
                loc.LocationNo = 10;
                loc.Location=EntityUtils.GetBin(line.WH.Code,linedto.Location.Code);//库位
                loc.ItemInfo = line.ItemInfo;
                loc.InvUOM = line.InvUom;
                loc.DealItemTime = DateTime.Now;
                loc.ChildLotInvalidationDate = DateTime.MinValue;
            }
        }

        private static void LineDefault(ShipLine line, ShipLineAITDTOData linedto)
        {
            Ship doc = line.Ship;

            if (linedto.DocLineNo > 0)
            {
                line.DocLineNo = linedto.DocLineNo;
            }
            else
            {
                line.DocLineNo = doc.ShipLines.Count*10;
            }

            //组织
            line.Org = doc.Org;
            line.ShipperOrg = doc.Org;
            line.AccountOrg = doc.Org;

            //物料/单位
            if (linedto.ItemInfo == null) throw new Exception("ItemInfo 必填");
            ItemMaster item = EntityUtils.GetEntityByCode<ItemMaster>(linedto.ItemInfo.ItemCode);
            line.ItemInfo = new ItemInfo()
            {
                ItemID = item,
                ItemCode = item.Code,
                ItemName = item.Name,
            };
            if (linedto.ItemInfo.ItemGrade >= 0)
            {
                line.ItemInfo.ItemGrade= GradeEnum.GetFromValue(linedto.ItemInfo.ItemGrade); //等级
            }
            if (linedto.ItemInfo.ItemPotency >= 0)
            {
                line.ItemInfo.ItemPotency = ElementEnum.GetFromValue(linedto.ItemInfo.ItemPotency); //成分
            }

            //批号
            if (linedto.LotInfo != null && !string.IsNullOrEmpty(linedto.LotInfo.LotCode))
            {
                UFIDA.U9.Lot.LotMaster lot = EntityUtils.GetLot(linedto.LotInfo.LotCode, item.Code);
                line.LotInfo = new UFIDA.U9.Lot.LotMasterInfo()
                {
                    LotMaster = lot,
                    LotCode = lot.LotCode,
                    LotValidDate = lot.ValidDate,
                    DisabledDatetime = lot.InvalidTime
                };
            }

            //扩展字段处理
            if (linedto.DescFlexField != null)
            {
                line.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                DTOUtils.DTOPropCopy(linedto.DescFlexField, line.DescFlexField);
            }

            //其它
            line.Project = EntityUtils.GetEntityByCode<Project>(linedto.Project);//项目
            if (linedto.DonationType >= 0)
                line.DonationType = UFIDA.U9.CBO.SCM.Enums.FreeTypeEnum.GetFromValue(linedto.DonationType);//免费类型
            //line.ShipConfirmDate = doc.ShipConfirmDate;
            line.StateMachineID = Guid.Empty;
            line.ConfirmDate = doc.BusinessDate;
            line.PreMaturityDate = doc.BusinessDate;
            line.MaturityDate = doc.BusinessDate;
            line.ShipmentRule = doc.ShipmentRule;//出货原则
            if (String.IsNullOrEmpty(linedto.WH?.Code)) throw new Exception("WH 必填");
            line.WH = EntityUtils.GetEntityByCode<Warehouse>(linedto.WH.Code);//存储地点
            if (line.WH!=null&&line.WH.Manager!=null)
            {
                line.WhMan = line.WH.Manager; //库管员
            }
            if (linedto.StorageType > -1)
            {
                line.StorageType = UFIDA.U9.CBO.Enums.StorageTypeEnum.GetFromValue(linedto.StorageType);//存储类型
            }
            else
            {
                line.StorageType = UFIDA.U9.CBO.Enums.StorageTypeEnum.GetFromValue(4);//存储类型
            }
            line.Status = ShipStateEnum.GetFromValue(1);
            line.ShipToSite = doc.PayerSite;
            line.PayerSite = doc.PayerSite;
            line.CreditObj = doc.PayerSite;
            line.BillToSite = doc.PayerSite;
            line.AC = doc.AC;
            line.Payer = doc.Payer;
            line.Seller = doc.Seller;
            line.SaleDept = doc.SaleDept;
            line.SeibanAlterable = UFIDA.U9.CBO.SCM.Enums.SeibanAlterableEnum.GetFromValue(3);
            line.ReceivableTerm = doc.ReceivableTerm;
            line.PreRecObject = doc.PreRecObject;
            line.InvoiceAccording = doc.InvoiceAccording;
            line.HandleDept = doc.SaleDept;
            line.ConfirmTerm = doc.ConfirmTerm;
            line.ConfirmAccording = doc.ConfirmAccording;
            line.ConfirmMode=doc.ConfirmMode;

            line.DiscountRate = 1;

            line.TradeRatetoBase = 1;
            line.TCToACExRate = 1;
            line.PriceRatetoBase = 1;
            line.IUToIMU = 1;
            line.IsConfirmDateChangable = true;
            line.IsMaturityDateChangable = true;
            line.IsPriceListModify = true;
            line.IsPriceIncludeTax = true;
            line.IsPreRecChangeable = true;
            line.IsPossessCredit = true;
            line.IsNoSOShipment = doc.IsNoSOShipment;
            line.IsModifyTCToACExRate = true;
            line.IsModifyTBUToPBU = true;
            line.IsModifyLot = true;
            line.IsMakeOutInvoice = true;
            line.IsKit = true;
            line.IsItemVersionChangable = true;
            line.IsInvoiceUpdate = true;
            line.IsChangeProcessQty = true;
            line.IsAllowReturn = true;
            line.InvRatetoBase = 1;
            line.IncomeConfirmRule = UFIDA.U9.CBO.Enums.RevenueConfirmRuleEnum.GetFromValue(2);
            line.CostRatetoBase = 1;
        }

        private static void FromSOLine(ShipLine line,ShipLineAITDTOData linedto)
        {
            Ship doc = line.Ship;

            String path = $"SOLine.SO.DocNo='{linedto.SrcDocInfo.DocNo}' and SOLine.DocLineNo={linedto.SrcDocInfo.DocLineNo} and DocSubLineNo=10";
            SOShipline shipline = SOShipline.Finder.Find(path);
            if (shipline == null) throw new Exception($"查询SO计划行失败,Path:[{path}]");
            SOLine soline = shipline.SOLine;
            SO so = soline.SO;

            if (linedto.ItemInfo.ItemCode != soline.ItemInfo.ItemCode)
                throw new Exception($"来源单据物料[{soline.ItemInfo.ItemCode}]与传入物料[{linedto.ItemInfo.ItemCode}]不同");
            //来源单据 赋值
            if (soline.Project != null)
            {
                line.Project = soline.Project;//项目
            }
            line.SrcSysVersion = so.SysVersion;
            line.SrcDocVer = so.Version;
            line.SrcDocType = ShipSrcDocTypeEnum.GetFromValue(1);
            line.SrcDocTransType = so.DocType.ID;
            line.SrcDocSubLineNo = shipline.DocSubLineNo;
            line.SrcDocSubLineKey = shipline.ID;
            line.SrcDocPriceTC = soline.OrderPriceTC;
            line.SrcDocOwnedOrg = doc.Org;
            line.SrcDocNo = so.DocNo;
            line.SrcDocLineNo = soline.DocLineNo;
            line.SrcDocLineKey = soline.ID;
            line.SrcDocKey = so.ID;
            line.SrcDocDate = so.BusinessDate;
            //来源SO 赋值
            line.SOVer = so.Version;
            line.SOTDocType = so.DocType.ID;
            line.SOSysVersion = so.SysVersion;
            line.SOSubLineNo = shipline.DocSubLineNo;
            line.SOSubLineKey = shipline.ID;
            line.SOOwnedOrg = doc.Org;
            line.SONo = so.DocNo;
            line.SOLineNo = soline.DocLineNo;
            line.SOLineKey = soline.ID;
            line.SOKey = so.ID;
            line.SODate = so.BusinessDate;

            //其它
            line.PriceSource = PriceSourceEnum.GetFromValue(3);//价格来源=来源单据
            doc.SrcDocType = ShipSrcDocTypeEnum.GetFromValue(1);//来源单据类型=订单
            doc.PreRecObject = UFIDA.U9.CBO.SCM.PreRecPolicy.PreRecObjectEnum.GetFromValue(1);//预收环节=订单
            line.PreRecObject = doc.PreRecObject;
            doc.IsNoSOShipment = false;
            doc.ShipmentRule = doc.OrderBy.Customer.ShippmentRule;//出货原则
            line.ShipmentRule=doc.ShipmentRule;
        }

        private static void CreateHead(Ship doc, ShipAITDTOData dto)
        {
            //doc.DocNo = dto.DocNo;
            if (String.IsNullOrEmpty(dto.BusinessDate)) throw new Exception("BusinessDate 必填");
            doc.BusinessDate = DateTime.Parse(dto.BusinessDate);
            //doc.ShipConfirmDate = doc.BusinessDate;
            //doc.ShipDate = doc.BusinessDate;
            if (dto.DocumentType == null) throw new Exception("DocumentType 必填");
            doc.DocumentType = EntityUtils.GetEntityByCode<ShipDocType>(dto.DocumentType.Code);//单据类型
            

            //组织
            doc.Org = Context.LoginOrg;
            doc.ShipOrg = doc.Org;
            doc.SettlementOrg = doc.Org;
            doc.OperatingOrg = doc.Org;
            doc.InvoiceOrg = doc.Org;
            doc.AccountOrg = doc.Org;
            //客户
            if (dto.OrderBy == null) throw new Exception("OrderBy 必填");
            Customer cust = EntityUtils.GetEntityByCode<Customer>(dto.OrderBy.Code);
            doc.OrderBy = new CustomerMISCInfo()
            {
                Customer = cust,
                Code = cust.Code,
                Name = cust.Name,
                ShortName = cust.ShortName,
            };
            doc.Payer = doc.OrderBy;
            if (cust.CustomerSites == null || cust.CustomerSites.Count == 0)
                throw new Exception($"客户[{cust.Code}]位置为空");
            doc.PayerSite = new CustomerSiteMISCInfo()
            {
                CustomerSite = cust.CustomerSites[0],
                Code = cust.CustomerSites[0].Code,
                Name = cust.CustomerSites[0].Name,
            };
            doc.BillToSite = doc.PayerSite;
            //税组合 单头
            if(dto.TaxSchedule != null)
            {
                //传入有限
                doc.TaxSchedule = EntityUtils.GetEntityByCode<TaxSchedule>(dto.TaxSchedule.Code);
            }
            else
            {
                //其次客户上税组合
                doc.TaxSchedule = cust.TaxSchedule;
            }

            //扩展字段处理
            if (dto.DescFlexField != null)
            {
                doc.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                DTOUtils.DTOPropCopy(dto.DescFlexField, doc.DescFlexField);
            }

            //其它
            doc.ConfirmTerm = cust.ARConfirmTerm;//立账条件
            doc.ConfirmMode = doc.DocumentType.ConfirmMode;//立账方式
            doc.ConfirmAccording = doc.DocumentType.ConfirmAccording;//立账依据
            doc.InvoiceAccording = doc.DocumentType.InvoiceAccording;//开票依据
            doc.BizType = doc.DocumentType.BusinessType;//业务类型

            doc.WorkFlowID = Guid.Empty;
            doc.StateMachineID = Guid.Empty;
            doc.WarpRatio = 0.05M;//溢短装（％）
            doc.TC = EntityUtils.GetEntityByCode<Currency>("C001");
            doc.FC = doc.TC;
            doc.AC = doc.TC;
            
            doc.Status = ShipStateEnum.GetFromValue(1);
            doc.Seller = EntityUtils.GetEntityByCode<Operators>(dto.Seller);//业务员
            doc.SaleDept = EntityUtils.GetEntityByCode<Department>(dto.SaleDept);//部门
            doc.ReceivableTerm = cust.RecervalTerm;
            doc.PreRecObject = UFIDA.U9.CBO.SCM.PreRecPolicy.PreRecObjectEnum.GetFromValue(2);//预收环节=出货
            doc.KeepAccountsPeriod = EntityUtils.getPostPeriod(doc.BusinessDate);
            doc.IncomeConfirmRule = UFIDA.U9.CBO.Enums.RevenueConfirmRuleEnum.GetFromValue(2);//收入规则

            doc.InsureRatio = 1.1m;
            doc.IsPriceIncludeTax = true;
            doc.IsPreRecChangeable = true;
            doc.IsNoSOShipment = true;
            doc.IsNoCreditCheck = true;
            doc.IsModPriceList = true;
            doc.IsModifyTC = true;
            doc.IsModifyExRateType = true;
            doc.IsModifyAC = true;
            doc.IsInvoiceOrgChangeable = true;
            doc.IsAccountOrgChangeable = true;
            doc.ACToFCExRate = 1;
            doc.ShipMode = UFIDA.U9.SM.Enums.ShipModeEnum.GetFromValue(dto.ShipMode);//出货方式

            //会计期间子表
            SOBPeriod per = SOBPeriod.Create(doc);
            per.SOBPeriods = doc.KeepAccountsPeriod;
            per.SOB = EntityUtils.getSetofBooks();
            per.Org = doc.Org;
        }

    }
}
